// utils/http.js
/**
 * HTTP请求工具类
 * 封装wx.request，统一处理请求和响应
 */

const config = require('../config');

// HTTP状态码常量
const HTTP_STATUS = {
  OK: 200,
  CREATED: 201,
  NO_CONTENT: 204,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  INTERNAL_ERROR: 500
};

// 错误消息映射
const ERROR_MESSAGES = {
  [HTTP_STATUS.BAD_REQUEST]: '请求参数错误',
  [HTTP_STATUS.UNAUTHORIZED]: '未授权，请重新登录',
  [HTTP_STATUS.FORBIDDEN]: '无权访问',
  [HTTP_STATUS.NOT_FOUND]: '请求的资源不存在',
  [HTTP_STATUS.INTERNAL_ERROR]: '服务器内部错误'
};

/**
 * 获取存储的token
 * @returns {string|null} token
 */
const getToken = () => {
  return wx.getStorageSync('token') || null;
};

/**
 * 清除登录信息
 */
const clearLoginInfo = () => {
  wx.removeStorageSync('token');
  wx.removeStorageSync('userInfo');
};

/**
 * 跳转到登录页
 */
const navigateToLogin = () => {
  wx.navigateTo({
    url: '/pages/login/login'
  }).catch(() => {
    // 如果已经在登录页，忽略错误
    console.log('已在登录页面');
  });
};

/**
 * 处理请求参数
 * @param {Object} options - 请求选项
 * @returns {Object} 处理后的请求选项
 */
const processOptions = (options) => {
  // 添加基础URL
  options.url = config.BASE_URL + options.url;

  // 初始化header
  options.header = {
    'content-type': 'application/json',
    ...options.header
  };

  // 如果有token，添加到header
  const token = getToken();
  if (token) {
    options.header['Authorization'] = `Bearer ${token}`;
  }

  return options;
};

/**
 * 处理响应错误
 * @param {number} statusCode - HTTP状态码
 * @param {Object} data - 响应数据
 * @returns {Error} 错误对象
 */
const handleResponseError = (statusCode, data) => {
  let errorMessage = ERROR_MESSAGES[statusCode] || `请求失败: ${statusCode}`;
  
  // 如果响应数据中有错误消息，优先使用
  if (data && data.message) {
    errorMessage = data.message;
  }
  
  return new Error(errorMessage);
};

/**
 * 判断是否为成功状态码
 * @param {number} statusCode - HTTP状态码
 * @returns {boolean} 是否成功
 */
const isSuccessStatus = (statusCode) => {
  return statusCode >= 200 && statusCode < 300;
};

/**
 * 发送HTTP请求
 * @param {Object} options - 请求选项
 * @returns {Promise<Object>} Promise对象
 */
const request = (options) => {
  return new Promise((resolve, reject) => {
    options = processOptions(options);

    wx.request({
      ...options,
      success: (res) => {
        // 请求成功，但需要检查状态码
        if (isSuccessStatus(res.statusCode)) {
          resolve(res.data);
        } else if (res.statusCode === HTTP_STATUS.UNAUTHORIZED) {
          // 未授权，清除token并跳转到登录页
          clearLoginInfo();
          navigateToLogin();
          reject(handleResponseError(res.statusCode, res.data));
        } else {
          // 其他错误
          reject(handleResponseError(res.statusCode, res.data));
        }
      },
      fail: (err) => {
        // 网络请求失败
        console.error('网络请求失败:', err);
        reject(new Error(`网络请求失败: ${err.errMsg || '网络异常'}`));
      }
    });
  });
};

/**
 * GET请求
 * @param {string} url - 请求URL
 * @param {Object} data - 请求参数
 * @param {Object} header - 请求头
 * @returns {Promise<Object>} Promise对象
 */
const get = (url, data = {}, header = {}) => {
  return request({
    url,
    method: 'GET',
    data,
    header
  });
};

/**
 * POST请求
 * @param {string} url - 请求URL
 * @param {Object} data - 请求参数
 * @param {Object} header - 请求头
 * @returns {Promise<Object>} Promise对象
 */
const post = (url, data = {}, header = {}) => {
  return request({
    url,
    method: 'POST',
    data,
    header
  });
};

/**
 * PUT请求
 * @param {string} url - 请求URL
 * @param {Object} data - 请求参数
 * @param {Object} header - 请求头
 * @returns {Promise<Object>} Promise对象
 */
const put = (url, data = {}, header = {}) => {
  return request({
    url,
    method: 'PUT',
    data,
    header
  });
};

/**
 * DELETE请求
 * @param {string} url - 请求URL
 * @param {Object} data - 请求参数
 * @param {Object} header - 请求头
 * @returns {Promise<Object>} Promise对象
 */
const del = (url, data = {}, header = {}) => {
  return request({
    url,
    method: 'DELETE',
    data,
    header
  });
};

/**
 * 文件上传
 * @param {string} url - 上传URL
 * @param {string} filePath - 文件路径
 * @param {string} name - 文件对应的 key
 * @param {Object} formData - 额外的表单数据
 * @returns {Promise<Object>} Promise对象
 */
const uploadFile = (url, filePath, name = 'file', formData = {}) => {
  return new Promise((resolve, reject) => {
    const token = getToken();
    const header = {};
    
    if (token) {
      header['Authorization'] = `Bearer ${token}`;
    }

    wx.uploadFile({
      url: config.BASE_URL + url,
      filePath,
      name,
      formData,
      header,
      success: (res) => {
        try {
          const data = JSON.parse(res.data);
          if (res.statusCode >= 200 && res.statusCode < 300) {
            resolve(data);
          } else {
            reject(handleResponseError(res.statusCode, data));
          }
        } catch (error) {
          reject(new Error('响应数据解析失败'));
        }
      },
      fail: (err) => {
        reject(new Error(`文件上传失败: ${err.errMsg}`));
      }
    });
  });
};

module.exports = {
  request,
  get,
  post,
  put,
  delete: del,
  uploadFile
};
